package com.aepryus.loom;

import java.util.*;
import java.lang.reflect.*;

public class UniversalPersist<T extends Domain> {
	private String name;
	private DomainInfo<T> info;
	private List<String> fields;

	private T[] ts;

	public UniversalPersist (String name,Class domain,T[] ts) {
		this.name = name;
		info = new DomainInfo<T>(domain);
		fields = new Vector<String>();
		this.ts = ts;
	}

	public String getName () {return name;}
	public void addField (String field) {fields.add(field);}

	public T create () throws PersistenceException {
		T domain = null;
		Map[] result = SQL.query("SELECT "+name+"ID.nextVal as ID FROM DUAL");
		try {

			domain = info.getConstructor().newInstance(new Object[]{});
			info.getSetter(name+"ID").invoke(domain,new Object[]{SQL.toLong(result[0].get("ID"))});

		} catch (InstantiationException e) { //
		} catch (IllegalAccessException e) { //
		} catch (InvocationTargetException e) { //
		}
		return domain;
	}
	public T selectByID (long id) throws PersistenceException {
		T[] domains = select(name+"ID = "+id,null);
		if (domains.length == 1) return domains[0];
		return null;
	}
	public T[] select (String where) throws PersistenceException {
		return select(where,null);
	}
	public T[] select (String where,String orderBy) throws PersistenceException {
		List<T> list = new Vector<T>();

		StringBuffer sb = new StringBuffer();
		sb.append("SELECT * FROM ").append(name);
		if (where != null && where.length() > 0) sb.append(" WHERE ").append(where);
		if (orderBy != null && orderBy.length() > 0) sb.append(" ORDER BY ").append(orderBy);

		Map[] result = SQL.query(sb.toString());

		for (Map row : result) {
			T domain = load(row);
			list.add(domain);
		}
		return list.toArray(ts);
	}
	protected void insert (T domain) throws PersistenceException {
		StringBuffer sb = new StringBuffer();
		sb.append("INSERT INTO ").append(name).append(" (");
		sb.append(") VALUES (");
		sb.append(")");
		SQL.update(sb.toString());
	}
	protected void update (T domain) throws PersistenceException {
		StringBuffer sb = new StringBuffer();
		sb.append("UPDATE ");
		sb.append(name);
		sb.append(" SET ");
		for (String field : fields)
			if (!field.equals(name+"ID")) {
				sb.append(field);
				sb.append("=");
				sb.append("");
				sb.append(",");
			}
		sb.deleteCharAt(sb.length());
		sb.append(" WHERE ");
		sb.append(name);
		sb.append("ID = ");
		sb.append(domain.getID());
		SQL.update(sb.toString());
	}
	protected void delete (T domain) throws PersistenceException {
		StringBuffer sb = new StringBuffer();
		sb.append("DELETE FROM ");
		sb.append(name);
		sb.append(" WHERE ");
		sb.append(name);
		sb.append("ID = ");
		sb.append(domain.getID());
		SQL.update(sb.toString());
	}

	public String unload (T domain) {
		StringBuffer sb = new StringBuffer();

		sb.append("INSERT INTO ");
		sb.append(name);
		sb.append(" (");
		for (String field : fields) {
			sb.append(field);
			sb.append(",");
		}
		sb.deleteCharAt(sb.length());
		for (String field : fields) {
			sb.append(domain.getByIntrospection(field));
			sb.append(",");
		}
		sb.deleteCharAt(sb.length());
		sb.append(")\r\n");

		return sb.toString();
	}

// Static ========================================================================
	private T load (Map map) throws PersistenceException {
		T domain = null;

		try {

			domain = info.getConstructor().newInstance(new Object[]{});

		} catch (InstantiationException e) { //
		} catch (IllegalAccessException e) { //
		} catch (InvocationTargetException e) { //
		}

		return domain;
	}
}

